package com.xzhuang.task.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdScheduler;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import com.xzhuang.task.quartz.QuartzJobFactory;
import com.xzhuang.task.quartz.QuartzJobFactoryDisallowConcurrentExecution;
import com.xzhuang.task.quartz.ScheduleTask;
import com.xzhuang.task.util.QuartzUtil;
import com.xzhuang.task.util.SpringContextUtil;

public class TaskServiceImpl implements TaskService {

	@Autowired
	private SchedulerFactoryBean schedulerFactoryBean;
    
	/***
	 * author : zyf
	 * 添加一个调度任务
	 */
	public void addTask(ScheduleTask task) throws Exception {
		if (task == null || !ScheduleTask.STATUS_RUNNING.equals(task.getJobStatus())) {
			return;
		}
		Scheduler scheduler = getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(task.getJobName(), task.getJobGroup());
		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

		if (trigger == null) {
			Class clazz = ScheduleTask.CONCURRENT_IS.equals(task.getIsConcurrent()) ? QuartzJobFactory.class : QuartzJobFactoryDisallowConcurrentExecution.class;
			JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(task.getJobName(), task.getJobGroup()).withDescription(task.getDescription()).build();
			jobDetail.getJobDataMap().put("scheduleJob", task);
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCronExpression());
			trigger = TriggerBuilder.newTrigger().withIdentity(task.getJobName(), task.getJobGroup()).withDescription(task.getDescription()).withSchedule(scheduleBuilder).build();
			//trigger = TriggerBuilder.newTrigger().withIdentity(task.getJobName(), task.getJobGroup()).withSchedule(scheduleBuilder).build();
			scheduler.scheduleJob(jobDetail, trigger);
		} else {
			// Trigger已存在，那么更新相应的定时设置
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCronExpression());
			// 按新的cronExpression表达式重新构建trigger
			trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
			// 按新的trigger重新设置job执行
			scheduler.rescheduleJob(triggerKey, trigger);
		}
	}

	public void deleteTask(ScheduleTask task,String defaultGroupName) throws Exception {
		Scheduler scheduler = getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(task.getJobName(), task.getJobGroup());
		scheduler.pauseTrigger(triggerKey);
		scheduler.unscheduleJob(triggerKey);
		//JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());
		scheduler.deleteJob(JobKey.jobKey(task.getJobName(), task.getJobGroup()));
	}

	public void updateTaskTrigger(ScheduleTask task) throws Exception {
		/*Scheduler scheduler = getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(task.getJobName(), task.getJobGroup());
		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCronExpression());
		trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withDescription(task.getDescription()).withSchedule(scheduleBuilder).build();
		scheduler.rescheduleJob(triggerKey, trigger);*/
		//**********************zyf 2016.5.1
		deleteTask(task, QuartzUtil.defaultGroupName);
		addTask(task);
	}

	public void resumeTask(ScheduleTask task) throws Exception {
		Scheduler scheduler = getScheduler();
		JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());
		scheduler.resumeJob(jobKey);
	}

	public void pauseTask(ScheduleTask task) throws Exception {
		Scheduler scheduler = getScheduler();
		JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());
		scheduler.pauseJob(jobKey);

	}

	public List<ScheduleTask> findExeTaskList() throws Exception {

		Scheduler scheduler = getScheduler();
		GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
		//GroupMatcher<JobKey> matcher3 = GroupMatcher.groupContains("");
		
		
		Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
		List<ScheduleTask> jobList = new ArrayList<ScheduleTask>();

		for (JobKey jobKey : jobKeys) {
			List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
			for (Trigger trigger : triggers) {
				ScheduleTask job = new ScheduleTask();
				job.setJobName(jobKey.getName());
				job.setJobGroup(jobKey.getGroup());
				//job.setDescription("触发器:" + trigger.getKey());
				job.setDescription(trigger.getDescription());
				Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
				job.setJobStatus(triggerState.name());
				if (trigger instanceof CronTrigger) {
					CronTrigger cronTrigger = (CronTrigger) trigger;
					String cronExpression = cronTrigger.getCronExpression();
					job.setCronExpression(cronExpression);
				}
				jobList.add(job);
			}
		}

		return jobList;
	}

	public List<ScheduleTask> getRunningJob() throws SchedulerException {
		Scheduler scheduler = getScheduler();
		List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
		List<ScheduleTask> jobList = new ArrayList<ScheduleTask>(executingJobs.size());
		for (JobExecutionContext executingJob : executingJobs) {
			ScheduleTask job = new ScheduleTask();
			JobDetail jobDetail = executingJob.getJobDetail();
			JobKey jobKey = jobDetail.getKey();
			Trigger trigger = executingJob.getTrigger();
			job.setJobName(jobKey.getName());
			job.setJobGroup(jobKey.getGroup());
			job.setDescription("触发器:" + trigger.getKey());
			Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
			job.setJobStatus(triggerState.name());
			if (trigger instanceof CronTrigger) {
				CronTrigger cronTrigger = (CronTrigger) trigger;
				String cronExpression = cronTrigger.getCronExpression();
				job.setCronExpression(cronExpression);
			}
			jobList.add(job);
		}
		return jobList;
	}

	public Scheduler getScheduler() {
		return (StdScheduler) SpringContextUtil.getBean("schedulerFactoryBean");
	}

	public void runAJobNow(ScheduleTask scheduleJob) throws SchedulerException {
		Scheduler scheduler = getScheduler();
		JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
		scheduler.triggerJob(jobKey);
	}

}
